﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoolanSlide.BooCommon;
using Configuration;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using Shapes = Windows.UI.Xaml.Shapes;

namespace BoolanElement
{
    class BooRectangleDialog:BooTextShapesBase
    {
        BooRectangleDialogElement rectangleDialogElement;
        public BooRectangleDialogElement RectangleDialogElement
        {
            get { return rectangleDialogElement; }
            set { rectangleDialogElement = value; }
        }

        Shapes.Path rectangleDialog;
        public Shapes.Path RectangleDialog
        {
            get { return rectangleDialog; }
            set { rectangleDialog = value; }
        }

        public PathFigure DialogFigure;

        public BezierSegment RoundedLeftTop;

        public LineSegment LineTop;

        public BezierSegment RoundedRightTop;

        public LineSegment LineRight;

        public BezierSegment RoundedRightBottom;

        public LineSegment DialogLine0;

        public LineSegment DialogLine1;

        public LineSegment DialogLine2;

        public LineSegment LineBottom;

        public BezierSegment RoundedLeftBottom;

        public LineSegment LineLeft;

        public override Shapes.Shape Shape
        {
            get { return rectangleDialog; }
        }

        public override BooTextShapesBaseElement TextShapesBaseElement
        {
            get { return rectangleDialogElement; }
        }

        public override BooElement Element
        {
            get
            {
                return rectangleDialogElement;
            }
            set
            {
                rectangleDialogElement = (BooRectangleDialogElement)value;
            }
        }

        public Canvas ArrowControlPoint;

        public BooRectangleDialog(BooRectangleDialogElement element, SaveForRedoUndo saveForRedoUndo)
            : base(element)
        {
            this.rectangleDialogElement = element;
            InitOriginal();
            base.saveForRedoUndo = saveForRedoUndo;
            Focus.InitFocusEvent(this);
            InitializeControlPoint();
        }

        public BooRectangleDialog(BooRectangleDialogElement element)
            : base(element)
        {
            this.rectangleDialogElement = element;
            InitOriginalForThumbNails();
            InitializeControlPoint();
        }

        public override void InitShape()
        {
            rectangleDialog = CreateRectangleDialog(rectangleDialogElement.ShapeWidth, rectangleDialogElement.ShapeHeight,  rectangleDialogElement.LineDialog1EndPoint);
            rectangleDialogElement.LineDialog1EndPoint = DialogLine1.Point;
            //new Shapes.Path();
            //rectangleDialog.Data = new PathGeometry();
            //((PathGeometry)rectangleDialog.Data).Figures = new PathFigureCollection();
            //((PathGeometry)rectangleDialog.Data).Figures.Add(new PathFigure());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments = new PathSegmentCollection();
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new BezierSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new LineSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new BezierSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new LineSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new BezierSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new LineSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new LineSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new LineSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new BezierSegment());
            //((PathGeometry)rectangleDialog.Data).Figures[0].Segments.Add(new LineSegment());

            //DialogFigure.IsClosed = true;

            //DialogFigure.StartPoint = new Point(this.rectangleDialogElement.FigureStartPoint.X,
            //    this.rectangleDialogElement.FigureStartPoint.Y);
            //RoundedLeftTop.Point1 = new Point(this.rectangleDialogElement.RoundedLeftTopPoint1.X,
            //    this.rectangleDialogElement.RoundedLeftTopPoint1.Y);
            //RoundedLeftTop.Point2 = new Point(this.rectangleDialogElement.RoundedLeftTopPoint2.X,
            //    this.rectangleDialogElement.RoundedLeftTopPoint2.Y);
            //RoundedLeftTop.Point3 = new Point(this.rectangleDialogElement.RoundedLeftTopPoint3.X,
            //    this.rectangleDialogElement.RoundedLeftTopPoint3.Y);
            //LineTop.Point = new Point(this.rectangleDialogElement.LineTopEndPoint.X,
            //    this.rectangleDialogElement.LineTopEndPoint.Y);
            //RoundedRightTop.Point1 = new Point(this.rectangleDialogElement.RoundedRightTopPoint1.X,
            //    this.rectangleDialogElement.RoundedRightTopPoint1.Y);
            //RoundedRightTop.Point2 = new Point(this.rectangleDialogElement.RoundedRightTopPoint2.X,
            //    this.rectangleDialogElement.RoundedRightTopPoint2.Y);
            //RoundedRightTop.Point3 = new Point(this.rectangleDialogElement.RoundedRightTopPoint3.X,
            //    this.rectangleDialogElement.RoundedRightTopPoint3.Y);
            //LineRight.Point = new Point(this.rectangleDialogElement.LineRightEndPoint.X,
            //    this.rectangleDialogElement.LineRightEndPoint.Y);
            //RoundedRightBottom.Point1 = new Point(this.rectangleDialogElement.RoundedRightBottomPoint1.X,
            //    this.rectangleDialogElement.RoundedRightBottomPoint1.Y);
            //RoundedRightBottom.Point2 = new Point(this.rectangleDialogElement.RoundedRightBottomPoint2.X,
            //    this.rectangleDialogElement.RoundedRightBottomPoint2.Y);
            //RoundedRightBottom.Point3 = new Point(this.rectangleDialogElement.RoundedRightBottomPoint3.X,
            //    this.rectangleDialogElement.RoundedRightBottomPoint3.Y);
            //DialogLine1.Point = new Point(this.rectangleDialogElement.LineDialog1EndPoint.X,
            //    this.rectangleDialogElement.LineDialog1EndPoint.Y);
            //DialogLine2.Point = new Point(this.rectangleDialogElement.LineDialog2EndPoint.X,
            //    this.rectangleDialogElement.LineDialog2EndPoint.Y);
            //LineBottom.Point = new Point(this.rectangleDialogElement.LineBottomEndPoint.X,
            //    this.rectangleDialogElement.LineBottomEndPoint.Y);
            //RoundedLeftBottom.Point1 = new Point(this.rectangleDialogElement.RoundedLeftBottomPoint1.X,
            //    this.rectangleDialogElement.RoundedLeftBottomPoint1.Y);
            //RoundedLeftBottom.Point2 = new Point(this.rectangleDialogElement.RoundedLeftBottomPoint2.X,
            //    this.rectangleDialogElement.RoundedLeftBottomPoint2.Y);
            //RoundedLeftBottom.Point3 = new Point(this.rectangleDialogElement.RoundedLeftBottomPoint3.X,
            //    this.rectangleDialogElement.RoundedLeftBottomPoint3.Y);
            //LineLeft.Point = new Point(this.rectangleDialogElement.LineLeftEndPoint.X,
            //    this.rectangleDialogElement.LineLeftEndPoint.Y);
        }

        private void InitializeControlPoint()
        {
            ArrowControlPoint = new Canvas();
            Ellipse elli = new Ellipse();
            elli.Width = FocusEllipses.FocusEllipsesDiameter;
            elli.Height = FocusEllipses.FocusEllipsesDiameter;
            SolidColorBrush fillColor = new SolidColorBrush(ConstColor.TitleColor);
            SolidColorBrush strokeColor = new SolidColorBrush(Color.FromArgb(255, 255, 255, 255));
            elli.Fill = fillColor;
            elli.Stroke = strokeColor;
            elli.StrokeThickness = 1;
            ArrowControlPoint.Children.Add(elli);
            ArrowControlPoint.Width = 50;
            ArrowControlPoint.Height = 50;
            ArrowControlPoint.Background = new SolidColorBrush(Colors.Transparent);
            ArrowControlPoint.RenderTransform = new TranslateTransform();
            (ArrowControlPoint.RenderTransform as TranslateTransform).X = DialogLine1.Point.X - ArrowControlPoint.Width / 2;
            (ArrowControlPoint.RenderTransform as TranslateTransform).Y = DialogLine1.Point.Y - ArrowControlPoint.Height / 2;
            elli.RenderTransform = new TranslateTransform()
            {
                X = (ArrowControlPoint.Width - elli.Width) / 2,
                Y = (ArrowControlPoint.Height - elli.Height) / 2
            };
            BooCanvas.Children.Add(ArrowControlPoint);
            ArrowControlPoint.ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.TranslateY;
            ArrowControlPoint.ManipulationDelta += ArrowControlPoint_ManipulationDelta;
            ArrowControlPoint.Visibility = Visibility.Collapsed;
        }

        void ArrowControlPoint_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {

            double width = e.Delta.Translation.X;
            double height = e.Delta.Translation.Y;
            double angle = this.Element.ElementTransform.Rotate.Angle * Math.PI / 180;
            double marginX = height * Math.Sin(angle) + width * Math.Cos(angle);
            double marginY = height * Math.Cos(angle) - width * Math.Sin(angle);
            Point orig = DialogLine1.Point;
            orig.X += marginX;
            orig.Y += marginY;
            (ArrowControlPoint.RenderTransform as TranslateTransform).X += marginX;
            (ArrowControlPoint.RenderTransform as TranslateTransform).Y += marginY;
            rectangleDialogElement.LineDialog1EndPoint = orig;
           // ModifyRectangleDialog(rectangleDialogElement.ShapeWidth, rectangleDialogElement.ShapeHeight, DialogLine1.Point);
            rectangleDialogElement.PropertyChanged("Shape");
        }

        Windows.UI.Xaml.Shapes.Path CreateRectangleDialog(double width, double height, Point arrowPoint)
        { 
            Windows.UI.Xaml.Shapes.Path path = new Windows.UI.Xaml.Shapes.Path();
            path.Stroke = new SolidColorBrush(Color.FromArgb(100,100,100,4));
            path.StrokeThickness = 5;
            PathGeometry pathGeometry = new PathGeometry();
            DialogFigure = new PathFigure();
            DialogFigure.IsClosed = false;
            DialogFigure.StartPoint = new Point(0, 40);

            DialogLine0 = new LineSegment();
            DialogLine1 = new LineSegment();
            DialogLine1.Point = arrowPoint;

            DialogLine2 = new LineSegment();

            LineLeft = new LineSegment();
            LineLeft.Point = new Point(0, height - 40);
           
            RoundedLeftBottom = new BezierSegment();
            RoundedLeftBottom.Point1 = LineLeft.Point;
            RoundedLeftBottom.Point2 = new Point(0, height);
            RoundedLeftBottom.Point3 = new Point(40, height);
            

            LineBottom = new LineSegment();
            LineBottom.Point = new Point(width - 40, height);
           
            RoundedRightBottom = new BezierSegment();
            RoundedRightBottom.Point1 = LineBottom.Point;
            RoundedRightBottom.Point2 = new Point(width, height);
            RoundedRightBottom.Point3 = new Point(width, height - 40);
           

            LineRight = new LineSegment();
            LineRight.Point = new Point(width, 40);
           
            RoundedRightTop = new BezierSegment();
            RoundedRightTop.Point1 = LineRight.Point;
            RoundedRightTop.Point2 = new Point(width, 0);
            RoundedRightTop.Point3 = new Point(width - 40, 0);
           

            LineTop = new LineSegment();
            LineTop.Point = new Point(40, 0);
            
            RoundedLeftTop = new BezierSegment();
            RoundedLeftTop.Point1 = LineTop.Point;
            RoundedLeftTop.Point2 = new Point(0, 0);
            RoundedLeftTop.Point3 = new Point(0, 40);

            Direction direction = GetExternPoints(new Rect(new Point(0, 0), new Point(width, height)), arrowPoint);

            DialogFigure.Segments.Add(LineLeft);
            if (direction == Direction.Left)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedLeftBottom);
            DialogFigure.Segments.Add(LineBottom);
            if (direction == Direction.Down)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedRightBottom);
            DialogFigure.Segments.Add(LineRight);
            if (direction == Direction.Right)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedRightTop);
            DialogFigure.Segments.Add(LineTop);
            if (direction == Direction.Up)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedLeftTop);

            pathGeometry.Figures.Add(DialogFigure);
            path.Data = pathGeometry;
            return path;
        }

        void ModifyRectangleDialog(double width, double height, Point arrowPoint)
        {
            DialogFigure.Segments.Clear();

            DialogFigure.IsClosed = true;
            DialogFigure.StartPoint = new Point(0, 40);

            DialogLine1.Point = arrowPoint;

            LineLeft.Point = new Point(0, height - 40);

            RoundedLeftBottom.Point1 = LineLeft.Point;
            RoundedLeftBottom.Point2 = new Point(0, height);
            RoundedLeftBottom.Point3 = new Point(40, height);

            LineBottom.Point = new Point(width - 40, height);

            RoundedRightBottom.Point1 = LineBottom.Point;
            RoundedRightBottom.Point2 = new Point(width, height);
            RoundedRightBottom.Point3 = new Point(width, height - 40);

            LineRight.Point = new Point(width, 40);

            RoundedRightTop.Point1 = LineRight.Point;
            RoundedRightTop.Point2 = new Point(width, 0);
            RoundedRightTop.Point3 = new Point(width - 40, 0);

            LineTop.Point = new Point(40, 0);

            RoundedLeftTop.Point1 = LineTop.Point;
            RoundedLeftTop.Point2 = new Point(0, 0);
            RoundedLeftTop.Point3 = new Point(0, 40);

            Direction direction = GetExternPoints(new Rect(new Point(0, 0), new Point(width, height)), arrowPoint);

            DialogFigure.Segments.Add(LineLeft);
            if (direction == Direction.Left)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedLeftBottom);
            DialogFigure.Segments.Add(LineBottom);
            if (direction == Direction.Down)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedRightBottom);
            DialogFigure.Segments.Add(LineRight);
            if (direction == Direction.Right)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedRightTop);
            DialogFigure.Segments.Add(LineTop);
            if (direction == Direction.Up)
            {
                DialogFigure.Segments.Add(DialogLine1);
                DialogFigure.Segments.Add(DialogLine2);
                DialogFigure.Segments.Add(DialogLine0);
            }
            DialogFigure.Segments.Add(RoundedLeftTop);
        }

        public Direction GetExternPoints(Rect rect, Point point)
        {
            double sideLength = 40;
            Point[] points=new Point[2];
            points[0] = new Point(0,0);
            points[1] = new Point(0, 0);
            List<Direction> directions = BooMath.PointAtRectangle(rect, point);
            if (directions.Contains(Direction.Left))
            {
                double length=LineLeft.Point.Y - RoundedRightTop.Point1.Y;
                if (length < 40)
                {
                    if (length <= 0)
                    {
                        points[0] = new Point(0, rect.Height/2);
                        points[1] = new Point(0, rect.Height / 2);
                    }
                    else
                    {
                        sideLength = LineLeft.Point.Y - RoundedRightTop.Point1.Y;
                        points[0] = new Point(0, 40);
                        points[1] = new Point(0, rect.Bottom - 40);
                    }
                }
                else
                {
                    if (point.Y < 60)
                    {
                        points[0] = new Point(0, 40);
                        points[1] = new Point(0, 40 + sideLength);
                    }
                    else if (point.Y > rect.Bottom - 60)
                    {
                        points[0] = new Point(0, rect.Bottom - 40 - sideLength);
                        points[1] = new Point(0, rect.Bottom - 40);
                    }
                    else
                    {
                        points[0] = new Point(0, point.Y - sideLength / 2);
                        points[1] = new Point(0, point.Y + sideLength / 2);
                    }
                }
                LineLeft.Point = points[0];
                DialogLine2.Point=points[1];
                DialogLine0.Point = RoundedLeftBottom.Point1;
                return Direction.Left;
            }
            if (directions.Contains(Direction.Right))
            {
                double length = RoundedRightBottom.Point3.Y-LineRight.Point.Y;
                if (length < 40)
                {
                    if (length <= 0)
                    {
                        points[0] = new Point(rect.Width, rect.Height / 2);
                        points[1] = new Point(rect.Width, rect.Height / 2);
                    }
                    else
                    {
                        points[0] = new Point(rect.Width, 40);
                        points[1] = new Point(rect.Width, rect.Bottom - 40);
                    }
                }
                else
                {
                    if (point.Y < 60)
                    {
                        points[0] = new Point(rect.Width, 40);
                        points[1] = new Point(rect.Width, 80);
                    }
                    else if (point.Y > rect.Bottom - 60)
                    {
                        points[0] = new Point(rect.Width, rect.Bottom - 80);
                        points[1] = new Point(rect.Width, rect.Bottom - 40);
                    }
                    else
                    {
                        points[0] = new Point(rect.Width, point.Y - 20);
                        points[1] = new Point(rect.Width, point.Y + 20);
                    }
                }
                LineRight.Point = points[1];
                DialogLine2.Point = points[0];
                DialogLine0.Point = RoundedRightTop.Point1;
                return Direction.Right;
            }
            if (directions.Contains(Direction.Up))
            {
                double length = RoundedRightTop.Point3.X-LineTop.Point.X;
                if (length < 40)
                {
                    if (length <= 0)
                    {
                        points[0] = new Point(rect.Width/2, 0);
                        points[1] = new Point(rect.Width/2,0);
                    }
                    else
                    {
                        points[0] = new Point(40,0);
                        points[1] = new Point(rect.Width-40, 0);
                    }
                }
                else
                {
                    if (point.X < 60)
                    {
                        points[0] = new Point(40, 0);
                        points[1] = new Point(80, 0);
                    }
                    else if (point.X > rect.Right - 60)
                    {
                        points[0] = new Point(rect.Right - 80, 0);
                        points[1] = new Point(rect.Right - 40, 0);
                    }
                    else
                    {
                        points[0] = new Point(point.X - 20, 0);
                        points[1] = new Point(point.X + 20, 0);
                    }
                }
                LineTop.Point = points[1];
                DialogLine2.Point = points[0];
                DialogLine0.Point = RoundedLeftTop.Point1;
                return Direction.Up;
            }
            if (directions.Contains(Direction.Down))
            {
                double length = LineBottom.Point.X-RoundedLeftBottom.Point3.X;
                 if (length < 40)
                 {
                     if (length <= 0)
                     {
                         points[0] = new Point(rect.Width / 2, rect.Height);
                         points[1] = new Point(rect.Width / 2, rect.Height);
                     }
                     else
                     {
                         points[0] = new Point(40, rect.Height);
                         points[1] = new Point(rect.Width - 40, rect.Height);
                     }
                 }
                 else
                 {
                     if (point.X < 60)
                     {
                         points[0] = new Point(40, rect.Bottom);
                         points[1] = new Point(80, rect.Bottom);
                     }
                     else if (point.X > rect.Right - 60)
                     {
                         points[0] = new Point(rect.Right - 80, rect.Bottom);
                         points[1] = new Point(rect.Right - 40, rect.Bottom);
                     }
                     else
                     {
                         points[0] = new Point(point.X - 20, rect.Bottom);
                         points[1] = new Point(point.X + 20, rect.Bottom);
                     }
                 }
                LineBottom.Point = points[0];
                DialogLine2.Point = points[1];
                DialogLine0.Point = RoundedRightBottom.Point1;
                return Direction.Down;
            }
            return Direction.Center;
        }

        public override void ReSizeUI(double x, double y)
        {

            if (rectangleDialogElement.ElementTransform.Width + x <80 || rectangleDialogElement.ElementTransform.Height + y < 80)
            {
                return;
            }

            rectangleDialogElement.ElementTransform.Width = rectangleDialogElement.ElementTransform.Width + x;
            rectangleDialogElement.ElementTransform.Height = rectangleDialogElement.ElementTransform.Height + y;

            rectangleDialogElement.ShapeWidth = rectangleDialogElement.ElementTransform.Width;
            rectangleDialogElement.ShapeHeight = rectangleDialogElement.ElementTransform.Height;

            rectangleDialogElement.TextWidth = rectangleDialogElement.ElementTransform.Width;
            rectangleDialogElement.PropertyChanged("Shape");

            Focus.SetFocuseEllipseMargin(rectangleDialogElement.ShapeWidth, rectangleDialogElement.ShapeHeight);
        }

        public override void ReMargin(double x, double y)
        {
            this.Element.ElementTransform.Translate.X += x;
            this.Element.ElementTransform.Translate.Y += y;
        }

        public override void ApplySize()
        {
            base.ApplySize();
            ModifyRectangleDialog(rectangleDialogElement.ShapeWidth, rectangleDialogElement.ShapeHeight, rectangleDialogElement.LineDialog1EndPoint);
            this.FullGrid.Width = rectangleDialogElement.ElementTransform.Width;
            this.FullGrid.Height = rectangleDialogElement.ElementTransform.Height;
            this.CenterStack.Width = rectangleDialogElement.ElementTransform.Width;
            TextBox.Width = rectangleDialogElement.ElementTransform.Width;
            (ArrowControlPoint.RenderTransform as TranslateTransform).X = DialogLine1.Point.X - ArrowControlPoint.Width / 2;
            (ArrowControlPoint.RenderTransform as TranslateTransform).Y = DialogLine1.Point.Y - ArrowControlPoint.Height / 2;
            
        }

        public override void GotFocus()
        {
            base.GotFocus();
            if (ArrowControlPoint != null)
                ArrowControlPoint.Visibility = Visibility.Visible;
        }

        public override void LostFocus()
        {
            base.LostFocus();
            if(ArrowControlPoint!=null)
                ArrowControlPoint.Visibility = Visibility.Collapsed;
        }

        
    }
}
